package com.saturday.data.scope;

import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.saturday.data.scope.annotation.DataColumn;
import com.saturday.data.scope.annotation.DataScope;
import com.saturday.data.scope.constants.SqlWhereRelationEnum;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 数据权限处理器抽象类
 */
@Slf4j
public abstract class AbstractDataPermissionHandler implements DataPermissionHandler {

    /**
     * @param where             原生where条件，没有为null
     * @param mappedStatementId Example:com.saturday.auth.UserInfoMapper.selectUserInfos  依据此值可以反射获取到类上的注解信息
     * @return
     */
    @SneakyThrows
    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        String clazz = mappedStatementId.substring(0, mappedStatementId.lastIndexOf("."));
        String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(".") + 1);
        try {
            Method[] declaredMethods = ReflectionUtils.getDeclaredMethods(Class.forName(clazz));
            if (null != declaredMethods) {
                for (Method method : declaredMethods) {
                    if (method.getName().equals(methodName)) {
                        Annotation[] annotations = method.getAnnotations();
                        if (null != annotations) {
                            for (Annotation annotation : annotations) {
                                if (annotation instanceof DataColumn) {
                                    if (!isExecute(((DataColumn) annotation).dataRuleKey())) {
                                        return where;
                                    }

                                    return getDataColumnWhereSql(where, (DataColumn) annotation);
                                }

                                if (annotation instanceof DataScope) {
                                    DataColumn[] dataColumns = ((DataScope) annotation).value();
                                    SqlWhereRelationEnum[] sqlWhereRelationEnums = ((DataScope) annotation).dataColumnRelation();

                                    return getDataColumnsWhereSql(where, dataColumns, sqlWhereRelationEnums);
                                }
                            }
                        } else {
                            break;
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            log.error("{}无法反射获取", mappedStatementId);
            throw e;
        }
        return where;
    }

    /**
     * 用于判断依据注解是否是可以执行的
     *
     * @param key
     * @return
     */
    protected abstract boolean isExecute(String key);

    /**
     * 自行实现数据权限的sql拼接，针对单个注解{@link DataColumn}
     *
     * @param where
     * @param dataColumn
     * @return
     * @throws JSQLParserException
     */
    protected abstract Expression getDataColumnWhereSql(Expression where, DataColumn dataColumn) throws JSQLParserException;

    /**
     * 自行实现数据权限的sql拼接,针对多个注解{@link DataColumn}
     *
     * @param where
     * @param dataColumns
     * @return
     * @throws JSQLParserException
     */
    protected abstract Expression getDataColumnsWhereSql(Expression where, DataColumn[] dataColumns, SqlWhereRelationEnum[] sqlWhereRelationEnums) throws JSQLParserException;

}
